/**
 * 
 */
package com.sangharsh.core.algo.location;

import com.sangharsh.core.algo.StopNode;
import com.sangharsh.core.algo.Vertex;

/**
 * @author pradeep
 * 
 */
public class LocationUtil {

	public static final StopNode getClosestNode(Vertex destinationVertex) {
		Location location = destinationVertex.getLocation();
		return getClosestNode(location, destinationVertex.getCode());
	}

	public static final StopNode getClosestNode(Location vertexLocation, String ignoreCode) {
		double minDistance = 0;
		StopNode closest = null;
		for (StopNode node : StopNode.values()) {
			if (node.isActive()) {
				Location location = node.getLocation();
				double distance = distance(vertexLocation.getLatitude(), vertexLocation.getLongitude(), location.getLatitude(), location.getLongitude(), 'K');
				if (!node.getCode().equals(ignoreCode) && (closest == null || distance < minDistance)) {
					minDistance = distance;
					closest = node;
				}
			}
		}
		if (minDistance < 50) {
			return closest;
		}
		return null;
	}

	public static double distance(Location first, Location second) {
		return distance(first.getLatitude(), first.getLongitude(),
				second.getLatitude(), second.getLongitude(), 'K');
	}

	private static double distance(double lat1, double lon1, double lat2,
			double lon2, char unit) {
		double theta = lon1 - lon2;
		double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2))
				+ Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2))
				* Math.cos(deg2rad(theta));
		dist = Math.acos(dist);
		dist = rad2deg(dist);
		dist = dist * 60 * 1.1515;
		if (unit == 'K') {
			dist = dist * 1.609344;
		} else if (unit == 'N') {
			dist = dist * 0.8684;
		}
		return (dist);
	}

	/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
	/*::  This function converts decimal degrees to radians             :*/
	/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
	private static double deg2rad(double deg) {
	  return (deg * Math.PI / 180.0);
	}

	/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
	/*::  This function converts radians to decimal degrees             :*/
	/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
	private static double rad2deg(double rad) {
	  return (rad * 180.0 / Math.PI);
	}
	
	private static double distance(Location locationFrom, Location locationTo,
			char unit) {
		return distance(locationFrom.getLatitude(), locationFrom.getLongitude(), locationTo.getLatitude(), locationTo.getLongitude(), unit);
	}
}